package com.mdd.front.service.refund.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
import com.google.common.primitives.Longs;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.log.OrderRefundLog;
import com.mdd.common.entity.order.Order;
import com.mdd.common.entity.refund.OrderRefund;
import com.mdd.common.enums.*;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.order.OrderMapper;
import com.mdd.common.mapper.refund.OrderRefundMapper;
import com.mdd.common.plugin.notice.NoticeDriver;
import com.mdd.common.utils.FormulaUtil;
import com.mdd.common.utils.SnUtils;
import com.mdd.common.utils.TimeUtil;
import com.mdd.front.service.log.IOrderRefundLogService;
import com.mdd.front.service.refund.IOrderRefundService;
import com.mdd.front.validate.PageParam;
import com.mdd.front.validate.refund.OrderRefundParam;
import com.mdd.front.vo.refund.OrderRefundDetailVo;
import com.mdd.front.vo.refund.OrderRefundListVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 订单退款实现类
 */
@Slf4j
@Service
public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, OrderRefund> implements IOrderRefundService {

    @Resource
    OrderMapper orderMapper;

    @Resource
    OrderRefundMapper orderRefundMapper;

    @Resource
    private IOrderRefundLogService orderRefundLogService;



    /**
     * 订单退款列表
     *
     * @param pageParam 分页参数
     * @param params    搜索参数
     * @return PageResult<OrderRefundListVo>
     * @author slien
     */
    @Override
    public PageResult<OrderRefundListVo> list(PageParam pageParam, Map<String, String> params) {
        Integer page = pageParam.getPageNo();
        Integer limit = pageParam.getPageSize();

        QueryWrapper<OrderRefund> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("id");

        orderRefundMapper.setSearch(queryWrapper, params, new String[]{
                "=:sn:str",
                "=:orderId@order_id:int",
                "=:userId@user_id:int",
                "=:type:int",
                "=:orderTerminal@order_terminal:int",
                "=:transactionId@transaction_id:str",
                "=:orderAmount@order_amount:str",
                "=:refundAmount@refund_amount:str",
                "=:refundStatus@refund_status:int",
        });

        IPage<OrderRefund> iPage = orderRefundMapper.selectPage(new Page<>(page, limit), queryWrapper);

        List<OrderRefundListVo> list = new LinkedList<>();
        for (OrderRefund item : iPage.getRecords()) {
            OrderRefundListVo vo = new OrderRefundListVo();
            BeanUtils.copyProperties(item, vo);
            vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            list.add(vo);
        }

        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
    }

    /**
     * 订单退款详情
     *
     * @param id 主键参数
     * @return OrderRefund
     * @author slien
     */
    @Override
    public OrderRefundDetailVo detail(Integer id) {
        OrderRefund model = orderRefundMapper.selectOne(
                new QueryWrapper<OrderRefund>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在");
        OrderRefundDetailVo vo = new OrderRefundDetailVo();
        BeanUtils.copyProperties(model, vo);
        return vo;
    }

    /**
     * 订单退款新增
     *
     * @param orderRefundParam 参数
     * @author slien
     */
    @Override
    public OrderRefund add(OrderRefundParam orderRefundParam) {
        OrderRefund model = new OrderRefund();
        model.setSn(orderRefundParam.getSn());
        model.setOrderId(orderRefundParam.getOrderId());
        model.setUserId(orderRefundParam.getUserId());
        model.setType(orderRefundParam.getType());
        model.setOrderTerminal(orderRefundParam.getOrderTerminal());
        model.setTransactionId(orderRefundParam.getTransactionId());
        model.setOrderAmount(orderRefundParam.getOrderAmount());
        model.setRefundAmount(orderRefundParam.getRefundAmount());
        model.setRefundStatus(orderRefundParam.getRefundStatus());
        model.setCreateTime(TimeUtil.timestamp());
        model.setUpdateTime(TimeUtil.timestamp());
        model.setRemark(orderRefundParam.getRemark());
        orderRefundMapper.insert(model);
        return model;
    }

    /**
     * 订单退款编辑
     *
     * @param orderRefundParam 参数
     * @author slien
     */
    @Override
    public void edit(OrderRefundParam orderRefundParam) {
        OrderRefund model = orderRefundMapper.selectOne(
                new QueryWrapper<OrderRefund>()
                        .eq("id", orderRefundParam.getId())
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");

        model.setId(orderRefundParam.getId());
        model.setSn(orderRefundParam.getSn());
        model.setOrderId(orderRefundParam.getOrderId());
        model.setUserId(orderRefundParam.getUserId());
        model.setType(orderRefundParam.getType());
        model.setOrderTerminal(orderRefundParam.getOrderTerminal());
        model.setTransactionId(orderRefundParam.getTransactionId());
        model.setOrderAmount(orderRefundParam.getOrderAmount());
        model.setRefundAmount(orderRefundParam.getRefundAmount());
        model.setRefundStatus(orderRefundParam.getRefundStatus());
        orderRefundMapper.updateById(model);
    }

    /**
     * 订单退款删除
     *
     * @param id 主键ID
     * @author slien
     */
    @Override
    public void del(Integer id) {
        OrderRefund model = orderRefundMapper.selectOne(
                new QueryWrapper<OrderRefund>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");

        orderRefundMapper.delete(new QueryWrapper<OrderRefund>().eq("id", id));
    }

    @Override
    public boolean updateOrderStatusToPaid(WxPayRefundNotifyV3Result.DecryptNotifyResult reqInfo) {
        String status = reqInfo.getRefundStatus();
        String outTradeNo = reqInfo.getOutTradeNo();

        OrderRefund orderRefund = orderRefundMapper.selectOne(
                new QueryWrapper<OrderRefund>()
                        .eq("sn", outTradeNo)
                        .last("limit 1"));
        Assert.notNull(orderRefund, "退款订单数据不存在!");
        if (OrderRefundStatusEnum.SUCCESS.getStatus() == orderRefund.getRefundStatus()) {
            return true;
        }
        // 退款成功
        if ("SUCCESS".equalsIgnoreCase(status)) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
            orderRefund.setRefundTime(TimeUtil.dateToTimestamp(reqInfo.getSuccessTime()));
        } else if ("PROCESSING".equalsIgnoreCase(status)) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
        } else if ("ABNORMAL".equalsIgnoreCase(status)) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.FAILURE.getStatus());
        } else {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.CLOSE.getStatus());
        }
        BigDecimal refund = FormulaUtil.divide(new BigDecimal(reqInfo.getAmount().getTotal()), 100);
        orderRefund.setRefundAmount(refund);
        orderRefund.setTransactionId(reqInfo.getRefundId());
        // 更新退款单
        orderRefundMapper.updateById(orderRefund);
        // 保存记录退款日志
        OrderRefundLog refundLog = new OrderRefundLog();
        refundLog.setSn(orderRefund.getSn());
        refundLog.setRefundId(orderRefund.getId());
        refundLog.setType(1);
        refundLog.setOperatorId(1L);
        refundLog.setRefundAmount(orderRefund.getRefundAmount());
        refundLog.setRefundStatus(orderRefund.getRefundStatus());
        refundLog.setWechatRefundId(reqInfo.getRefundId());
        refundLog.setRefundMsg(reqInfo.toString());
        refundLog.setCreateTime(TimeUtil.timestamp());
        refundLog.setUpdateTime(TimeUtil.timestamp());
        orderRefundLogService.saveEntity(refundLog);
        return false;
    }

    @Override
    public void rebates(Long orderId,Long refundId,BigDecimal refundAmount, String remark) {
        Order model = orderMapper.selectById(orderId);
        if(!model.getOrderStatus().equals(OrderStatusEnum.FINISHED.getStatus())){
            new OperateException("该订单未完成，无法进行部分退款");
        }
        OrderRefundParam param = new OrderRefundParam();
        OrderRefund orderRefund = null;
        if(refundId!=0 && refundId != null){
             orderRefund = orderRefundMapper.selectOne(new QueryWrapper<OrderRefund>().
                    eq("order_id", orderId).eq("id", refundId));
            //退款金额和退款备注
            orderRefund.setRefundAmount(refundAmount);
            orderRefund.setOrderAmount(refundAmount);
            orderRefund.setRemark(remark);
            orderRefundMapper.updateById(orderRefund);
        }else {
            param.setOrderId(model.getId());
            param.setUserId(model.getUserId());
            param.setType(RefundOperateEnum.TYPE_USER.getType());//用户退款
            param.setOrderTerminal(ClientEnum.MNP.getCode());
            param.setTransactionId(model.getTransactionId());
            param.setSn(SnUtils.getRefundOrderSn());
            param.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
            //退款金额和退款备注
            param.setRefundAmount(refundAmount);
            param.setOrderAmount(refundAmount);
            param.setRemark(remark);
            orderRefund = this.add(param);
        }


        //插入退款日志
        OrderRefundLog orderRefundLogAli2 = new OrderRefundLog();
        orderRefundLogAli2.setSn(orderRefund.getSn());
        orderRefundLogAli2.setRefundId(orderRefund.getId());
        orderRefundLogAli2.setType(OperateEnum.TYPE_USER.getType());
        orderRefundLogAli2.setOperatorId(1L);
        orderRefundLogAli2.setRefundAmount(orderRefund.getRefundAmount());
        orderRefundLogAli2.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
        orderRefundLogAli2.setWechatRefundId("");
        orderRefundLogAli2.setRefundMsg("退款成功");
        orderRefundLogAli2.setCreateTime(TimeUtil.timestamp());
        orderRefundLogAli2.setUpdateTime(TimeUtil.timestamp());
        orderRefundLogAli2.setRefundStatus(orderRefund.getRefundStatus());
        orderRefundLogAli2.setRemark(orderRefund.getRemark());
        orderRefundLogService.saveEntity(orderRefundLogAli2);
    }

    @Override
    public OrderRefundDetailVo getOrderRefund(Long orderId) {
        OrderRefund orderRefund = orderRefundMapper.selectOne(new QueryWrapper<OrderRefund>().eq("order_id", orderId).last("limit 1"));
        if(orderRefund == null){
            return null;
        }
        OrderRefundDetailVo orderRefundDetailVo = new OrderRefundDetailVo();
        BeanUtils.copyProperties(orderRefund,orderRefundDetailVo);
        orderRefundDetailVo.setId(orderRefund.getId().intValue());
        orderRefundDetailVo.setRemark(orderRefund.getRemark());
        orderRefundDetailVo.setRefundAmount(orderRefund.getRefundAmount().toString());
        orderRefundDetailVo.setOrderAmount(orderRefund.getOrderAmount().toString());
        return orderRefundDetailVo;
    }
}
